package org.json.util;

import java.util.Enumeration;
import java.util.Vector;

/**
 * Class that encapsulates a JSONPath
 * A set of keys (Strings) that represents a path
 * in a JSON Tree
 * 
 * TODO: Currently implemented using Vector
 * Depending on performance tests, might be optimized to use
 * another structure, such as StringBuffer or another one
 * more suitable/effective...
 *    
 * @author diegoyam
 */
public class JSONPath extends Vector {
	
	public JSONPath() {
		super(32);
	}
	
	public JSONPath(Object[] elem) {
		super();
		if (elem == null)
			return;
		for (int i = 0; i < elem.length; ++i) {
			if (!(elem[i] instanceof String) &&
					!(elem[i] instanceof Integer))
				throw new IllegalArgumentException(
						"JSONPath support only Strings and Integers elements");
			addElement(elem[i]);
		}
	}

	public boolean equals(Object o) {
		if (o == null)
			return false;
		if (o == this)
			return true;
		if (o instanceof String)
			return (compareTo((String)o) == 0);
		if (o instanceof JSONPath)
			return (compareTo((JSONPath)o) == 0);
		return false;
	}
	
	public void push(int arrayIndex) {
		addElement(new Integer(arrayIndex));
	}

	public void push(String s) {
		addElement(s);
	}
	
	public Object pop() {
		if (isEmpty())
			return null;
		Object r = lastElement();
		removeElementAt(size()-1);
		return r;
	}
	
	public String toString() {
		if (isEmpty())
			return "Empty path";
		Enumeration e = elements();
		StringBuffer sb = new StringBuffer();
		int i = 0;
		while (e.hasMoreElements()) {
			Object o = e.nextElement();
			if (o instanceof String) {
				if (i != 0) sb.append('.');
				sb.append(o);
			} else {
				sb.append('[');
				sb.append(o);
				sb.append(']');
			}
			++i;
		}
		return sb.toString();
	}
	
	public String toSufixString(int fromIndex) {
		if (isEmpty())
			return "Empty sufix";
		StringBuffer sb = new StringBuffer();
		int i = fromIndex;
		while (i < size()) {
			Object o = elementAt(fromIndex);
			if (o instanceof String) {
				if (i != fromIndex) sb.append('.');
				sb.append((String)o);
			} else {
				sb.append('[');
				sb.append((Integer)o);
				sb.append(']');
			}
			++i;
		}
		return sb.toString();
	}
	
	public int depth() {
		return size() - 1;
	}
	
	public int compareTo(JSONPath path) {
		if (path.size() != size())
			return -1;
		for (int i = depth(); i >= 0; --i) {
			if (!elementAt(i).equals(path.elementAt(i)))
				return -1;
		}
		return 0;
	}

	public int compareTo(String stringPath) {
		return stringPath.compareTo(toString());
	}

	public int compareTo(String sufix, int fromIndex) {
//		Debug.debug("Comparing " + toString() + " to " + sufix + " from " + (fromDepth+1));
		if (fromIndex >= size())
			return -1;
		return sufix.compareTo(toSufixString(fromIndex));
	}

	public JSONPath copy() {
		Object[] data = new Object[size()];
		copyInto(data);
		return new JSONPath(data);
	}

	public String topKey() {
		return (String)lastElement().toString();
	}

	public int topIndex() {
		if (isEmpty() || !(lastElement() instanceof Integer)) 
			return -1;
		return ((Integer)lastElement()).intValue();
	}
}
